// Fill out your copyright notice in the Description page of Project Settings.


#include "MyPlayerController.h"

#include "MyPawn.h"
#include "DSP/SpectrumAnalyzer.h"
#include "GameFramework/PlayerInput.h"
#include "Kismet/KismetMathLibrary.h"

bool FloatEquality(float a, float b)
{
	//由于FLOAT的特殊性这种写法就是判断FLOAT类型是否等于6.0
	return FMath::Abs(a - b) < 0.0001;
};

AMyPlayerController::AMyPlayerController()
{
	SetActorEnableCollision(false);
}

void AMyPlayerController::BeginPlay()
{
	Super::BeginPlay();
	MyPawn = Cast<AMyPawn>(K2_GetPawn());
}

void AMyPlayerController::SetupInputComponent()
{
	Super::SetupInputComponent();
	//鼠标左键点击
	UPlayerInput::AddEngineDefinedActionMapping(FInputActionKeyMapping("LeftMouseDown", EKeys::LeftMouseButton, false));
	//鼠标右键按下
	UPlayerInput::AddEngineDefinedActionMapping(FInputActionKeyMapping("RightButtonDown", EKeys::RightMouseButton, false));
	//鼠标滚轮
	UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("MouseWheel", EKeys::MouseWheelAxis, 1.f));
	//鼠标X轴移动
	UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("TurnRate", EKeys::MouseX, 1.f));
	//鼠标Y轴移动
	UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("LookUpRate", EKeys::MouseY, 1.f));
	//W
	UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("MoveForward", EKeys::W, 1.f));
	//S
	UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("MoveForward", EKeys::S, -1.f));
	//E
	UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("MoveUp", EKeys::E, 1.f));
	//Q
	UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("MoveUp", EKeys::Q, -1.f));
	//A
	UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("MoveRight", EKeys::A, -1.f));
	//D
	UPlayerInput::AddEngineDefinedAxisMapping(FInputAxisKeyMapping("MoveRight", EKeys::D, 1.f));


	//左键按下
	InputComponent->BindAction("LeftMouseDown", IE_Pressed, this, &AMyPlayerController::OnLeftMouseButtonDown);
	//左键抬起
	InputComponent->BindAction("LeftMouseDown", IE_Released, this, &AMyPlayerController::OnLeftMouseButtonUp);
	//右键按下抬起
	InputComponent->BindAction("RightButtonDown", IE_Pressed, this, &AMyPlayerController::OnPressedRightMouseButton);
	InputComponent->BindAction("RightButtonDown", IE_Released, this, &AMyPlayerController::OnRealeasedRightMouseButton);
	//前后移动
	InputComponent->BindAxis("MoveForward", this, &AMyPlayerController::MoveForward);
	//左右移动
	InputComponent->BindAxis("MoveRight", this, &AMyPlayerController::MoveRight);
	//上下移动
	InputComponent->BindAxis("MoveUp", this, &AMyPlayerController::MoveUp);
	//Y轴转动
	InputComponent->BindAxis("LookUpRate", this, &AMyPlayerController::LookUpRate);
	//X轴转动
	InputComponent->BindAxis("TurnRate", this, &AMyPlayerController::TurnRate);
	//滚轮
	InputComponent->BindAxis("MouseWheel", this, &AMyPlayerController::MouseWheel);
}

void AMyPlayerController::OnLeftMouseButtonDown()
{
	TArray<TEnumAsByte<EObjectTypeQuery>> ObjTypes;
	FHitResult HitResult;
	FVector WorldLocation;
	FVector WorldDeirection;
	//WorldLocation时位置
	//WorldDeirection是方向
	DeprojectMousePositionToWorld(WorldLocation, WorldDeirection);
	//计算方向
	if (FMath::Abs(WorldDeirection.X) >= FMath::Abs(WorldDeirection.Y) && FMath::Abs(WorldDeirection.X) >= FMath::Abs(WorldDeirection.Z))
		MoveDirection = X_Direction;
	else if (FMath::Abs(WorldDeirection.Y) >= FMath::Abs(WorldDeirection.Z) && FMath::Abs(WorldDeirection.Y) >= FMath::Abs(WorldDeirection.Z))
		MoveDirection = Y_Direction;
	else if (FMath::Abs(WorldDeirection.Z) >= FMath::Abs(WorldDeirection.X) && FMath::Abs(WorldDeirection.Z) >= FMath::Abs(WorldDeirection.Y))
		MoveDirection = Z_Direction;
	//这里要注意 不要点到PAWN了
	bool result = GetHitResultUnderCursorForObjects(ObjTypes, true, HitResult);
	if (result) //鼠标光标碰撞检测
	{
		ClickLocation = HitResult.Location;
		//int32 item = HitResult.Item;
	}
	else
	{
		//点击到了空白位置
		ClickLocation = PointSpaceLocation();
	}
}

void AMyPlayerController::OnLeftMouseButtonUp()
{
}


void AMyPlayerController::MoveForward(float AxisValue)
{
	if (!FloatEquality(AxisValue, 0.0))
	{
		MyPawn->MoveForward(AxisValue * 100);
	}
}

void AMyPlayerController::MoveRight(float AxisValue)
{
	if (!FloatEquality(AxisValue, 0.0))
	{
		MyPawn->MoveRight(AxisValue * 100);
	}
}

void AMyPlayerController::MoveUp(float AxisValue)
{
	if (!FloatEquality(AxisValue, 0.0))
	{
		MyPawn->MoveUp_World(AxisValue);
	}
}

//上下旋转
void AMyPlayerController::LookUpRate(float AxisValue)
{
	if (IsInputKeyDown(EKeys::RightMouseButton))
	{
		MyPawn->FixedPointRotation_Y(-AxisValue * 3, this);
	}
	else if (IsInputKeyDown(EKeys::LeftMouseButton))
	{
		MouseMove();
	}
}

//左右旋转
void AMyPlayerController::TurnRate(float AxisValue)
{
	if (IsInputKeyDown(EKeys::RightMouseButton))
	{
		if (AxisValue != 0.0)
		{
			MyPawn->FixedPointRotation_X(AxisValue * 3, this);
		}
	}
	else if (IsInputKeyDown(EKeys::LeftMouseButton))
	{
		MouseMove();
	}
}

void AMyPlayerController::MouseWheel(float AxisValue)
{
	if (AxisValue != 0.0)
	{
		float Speed = 5.0;
		TArray<TEnumAsByte<EObjectTypeQuery>> ObjTypes;
		FHitResult HitResult;
		//这里要注意 不要点到PAWN了
		bool result = GetHitResultUnderCursorForObjects(ObjTypes, true, HitResult);
		if (result) //鼠标光标碰撞检测
		{
			ClickLocation = HitResult.Location;

			CameraZoom(AxisValue, HitResult.Distance, Speed, ClickLocation);
		}
		else
		{
			//点击到了空白位置
			ClickLocation = PointSpaceLocation();
			CameraZoom(AxisValue, 10.0, Speed, ClickLocation);
		}
	}
}


void AMyPlayerController::OnPressedRightMouseButton()
{
	//右键按下
	TArray<TEnumAsByte<EObjectTypeQuery>> ObjTypes;
	FHitResult HitResult;
	//这里要注意 不要点到PAWN了
	bool result = GetHitResultUnderCursorForObjects(ObjTypes, true, HitResult);
	if (result) //鼠标光标碰撞检测
	{
		ClickLocation = HitResult.Location;
		//int32 item = HitResult.Item;
	}
	else
	{
		//点击到了空白位置
		ClickLocation = PointSpaceLocation();
	}
}

void AMyPlayerController::OnRealeasedRightMouseButton()
{
}

void AMyPlayerController::CameraZoom(float AxisValue, float Diatance, float Clamp, FVector Location)
{
	if (Diatance >= Clamp)
	{
		FVector A = MyPawn->GetActorLocation();
		float Alpha = AxisValue / (100 / Clamp);
		FVector C = FMath::Lerp(A, Location, Alpha);
		MyPawn->SetActorLocation(C, true);
	}
}

void AMyPlayerController::MouseMove()
{
	FVector WorldLocation;
	FVector WorldDeirection;
	DeprojectMousePositionToWorld(WorldLocation, WorldDeirection);
	FVector A = GetMouseAndHorizontalPlaneHitLocation(WorldLocation, WorldDeirection, ClickLocation);
	FVector B = (ClickLocation - A) * 0.6;
	if (B.Size() <= 1000)
	{
		MyPawn->AddActorWorldOffset(B);
	}
}

FVector AMyPlayerController::GetMouseAndHorizontalPlaneHitLocation(FVector MouseLocation, FVector MouseDirection, FVector PointOnThePlane)
{
	float Return_X;
	float Return_Y;
	float Return_Z;

	if (MoveDirection == X_Direction)
	{
		Return_X = MouseLocation.X + MouseDirection.X * ((PointOnThePlane.X - MouseLocation.X) / MouseDirection.X);
		Return_Y = MouseLocation.Y + MouseDirection.Y * ((PointOnThePlane.X - MouseLocation.X) / MouseDirection.X);
		Return_Z = MouseLocation.Z + MouseDirection.Z * ((PointOnThePlane.X - MouseLocation.X) / MouseDirection.X);
	}
	else if (MoveDirection == Y_Direction)
	{
		Return_X = MouseLocation.X + MouseDirection.X * ((PointOnThePlane.Y - MouseLocation.Y) / MouseDirection.Y);
		Return_Y = MouseLocation.Y + MouseDirection.Y * ((PointOnThePlane.Y - MouseLocation.Y) / MouseDirection.Y);
		Return_Z = MouseLocation.Z + MouseDirection.Z * ((PointOnThePlane.Y - MouseLocation.Y) / MouseDirection.Y);
	}
	else if (MoveDirection == Z_Direction)
	{
		Return_X = MouseLocation.X + MouseDirection.X * ((PointOnThePlane.Z - MouseLocation.Z) / MouseDirection.Z);
		Return_Y = MouseLocation.Y + MouseDirection.Y * ((PointOnThePlane.Z - MouseLocation.Z) / MouseDirection.Z);
		Return_Z = MouseLocation.Z + MouseDirection.Z * ((PointOnThePlane.Z - MouseLocation.Z) / MouseDirection.Z);
	}
	return FVector(Return_X, Return_Y, Return_Z);
}

FVector AMyPlayerController::PointSpaceLocation()
{
	FVector WorldLocation;
	FVector WorldDeirection;
	DeprojectMousePositionToWorld(WorldLocation, WorldDeirection);
	return WorldLocation + WorldDeirection * 2000;
}
